import { ENUM_AUDIO_CLIP, ENUM_GAME_MODE, ENUM_UI_TYPE } from "../Enum";
import { StaticInstance } from "../StaticInstance";
import { groupArray, random, shuffle, sort, sortByFrequency } from "../Utils";
import AudioManager from "../manager/AudioManager";
import DataManager, { GAME_DATA } from "../manager/DataManager";
import PoolManager from "../manager/PoolManager";
import ToastManager from "../manager/ToastManager";
import { Point } from "../plugins/AINavigate";
import Car from "./Car";
import Player, { PLAYER_STATE } from "./Player";

// carolsail
const { ccclass, property } = cc._decorator;

@ccclass
export default class Level extends cc.Component {

    board: cc.Node = null
    playerRoot: cc.Node = null
    carRoot: cc.Node = null
    carColorIndexArr: number[] = []
    playerColorIndexArr: number[] = []

    init() {
        this.board = this.node.getChildByName('board')
        this.playerRoot = cc.find('players', this.node)
        this.carRoot = cc.find('cars', this.node)
        // 初始化
        const { BOARD_SIZE, COMBINE, LEVELS, CAR_POSX } = GAME_DATA
        let level_type = 8, level_total = 108
        // 游戏模式
        if (DataManager.instance.mode == ENUM_GAME_MODE.NORMAL) {
            if (LEVELS[DataManager.instance.level - 1]) {
                const { type, total } = LEVELS[DataManager.instance.level - 1]
                level_type = type
                level_total = total
            }
        } else {
            const randLevelArr = [{ type: 4, total: 12 }, { type: 5, total: 18 }, { type: 4, total: 24 }]
            const randLevel = randLevelArr[random(0, randLevelArr.length - 1)]
            level_type = randLevel.type
            level_total = randLevel.total
        }
        DataManager.instance.levelPlayerTotal = level_total
        // 多少辆车
        if (level_total % COMBINE != 0) {
            ToastManager.instance.show('初始化数据有误', { gravity: 'TOP', bg_color: cc.color(226, 69, 109, 255) })
            return
        }
        const car_nums = level_total / COMBINE
        // 初始化车辆和小人数据
        for (let i = 0; i < car_nums; i++) {
            const colorIndex = i % level_type
            this.carColorIndexArr.push(colorIndex)
            for (let j = 0; j < COMBINE; j++) {
                this.playerColorIndexArr.push(colorIndex)
            }
        }
        // 打乱
        shuffle(this.carColorIndexArr)
        shuffle(this.playerColorIndexArr)
        // 初始化车辆
        AudioManager.instance.playSound(ENUM_AUDIO_CLIP.CAR_START)
        const carIndex = this.carColorIndexArr.pop()
        if (carIndex >= 0) {
            const carNode = PoolManager.instance.getNode('Car', this.carRoot)
            const carComp = carNode.getComponent(Car)
            carComp.init(carIndex)
            carComp.setMove(CAR_POSX[1], CAR_POSX[3])
        }
        // 初始化地图和小人
        const boardLen = this.board.children.length
        let count = 0
        for (let i = boardLen - 1; i >= 0; i--) {
            const board = this.board.children[i]
            const x = i % 6
            const y = Math.floor(i / 6)
            // const testLabel = PoolManager.instance.getNode('TestLabel', board)
            // testLabel.getComponent(cc.Label).string = `${x},${y}`
            DataManager.instance.mapPoints.set(x + y * BOARD_SIZE, new Point(x, y))
            DataManager.instance.mapBoards.set(x + y * BOARD_SIZE, board)
            if (this.playerColorIndexArr.length && count < 36) {
                count++
                const colorIndex = this.playerColorIndexArr.pop()
                const player = PoolManager.instance.getNode('Player', this.playerRoot)
                const playerComp = player.getComponent(Player)
                playerComp.init(x, y, colorIndex)
            }
        }
        this.initMapPoints()
    }

    initMapPoints() {
        // 更新地图
        this.board.children.forEach((board, i) => {
            const x = i % 6
            const y = Math.floor(i / 6)
            const playerIndex = this.playerRoot.children.findIndex(player => (player.x == board.x && player.y == board.y) && player.getComponent(Player).state == PLAYER_STATE.IDLE)
            if (playerIndex !== -1) {
                DataManager.instance.mapPoints.delete(x + y * GAME_DATA.BOARD_SIZE)
            } else {
                DataManager.instance.mapPoints.set(x + y * GAME_DATA.BOARD_SIZE, new Point(x, y))
            }
        })

        // 更新可移动块高亮
        for (let i = 0; i < this.playerRoot.children.length; i++) {
            const playerNode = this.playerRoot.children[i]
            const playerComp = playerNode.getComponent(Player)
            const board = DataManager.instance.mapBoards.get(playerComp.posX + playerComp.posY * GAME_DATA.BOARD_SIZE)
            if (playerComp.state == PLAYER_STATE.IDLE) {
                if ((playerComp.checkMove()).length) {
                    board.color = new cc.Color().fromHEX('#7893D2')
                } else {
                    board.color = new cc.Color().fromHEX('#ffffff')
                }
            } else {
                board.color = new cc.Color().fromHEX('#ffffff')
            }
        }
    }

    resetMapPoints(x: number, y: number) {
        const board = DataManager.instance.mapBoards.get(x + y * GAME_DATA.BOARD_SIZE)
        DataManager.instance.mapPoints.set(x + y * GAME_DATA.BOARD_SIZE, new Point(x, y))
        board.color = new cc.Color().fromHEX('#ffffff')
        // 遍历所有待机player
        for (let i = 0; i < this.playerRoot.children.length; i++) {
            const playerNode = this.playerRoot.children[i]
            const playerComp = playerNode.getComponent(Player)
            if (playerComp.state == PLAYER_STATE.IDLE) {
                const board = DataManager.instance.mapBoards.get(playerComp.posX + playerComp.posY * GAME_DATA.BOARD_SIZE)
                if ((playerComp.checkMove()).length) {
                    board.color = new cc.Color().fromHEX('#7893D2')
                } else {
                    board.color = new cc.Color().fromHEX('#ffffff')
                }
            }
        }
    }

    // 站台车
    getTargetCar() {
        const carNode = this.carRoot.children.find(car => car.x == GAME_DATA.CAR_POSX[3])
        return carNode
    }

    // 后补车
    getReadyCar() {
        const carNode = this.carRoot.children.find(car => car.x == GAME_DATA.CAR_POSX[2])
        return carNode
    }
    // 途中的后补车
    getReadyCarRuning() {
        const carNode = this.carRoot.children.find(car => (car.x > GAME_DATA.CAR_POSX[0] && car.x < GAME_DATA.CAR_POSX[2]))
        return carNode
    }

    // 出站车
    getExitCar() {
        const carNode = this.carRoot.children.find(car => car.x == GAME_DATA.CAR_POSX[4])
        return carNode
    }

    // 车移动回调
    onCarMoveCallBack(posX: number) {
        switch (posX) {
            case GAME_DATA.CAR_POSX[3]: // 车到站
                // 补上后补车位
                const carIndex = this.carColorIndexArr.pop()
                if (carIndex >= 0) {
                    const carNode = PoolManager.instance.getNode('Car', this.carRoot)
                    const carComp = carNode.getComponent(Car)
                    carComp.init(carIndex)
                    carComp.setMove(GAME_DATA.CAR_POSX[0], GAME_DATA.CAR_POSX[2])
                }
                break
            case GAME_DATA.CAR_POSX[4]: // 车离开
                AudioManager.instance.playSound(ENUM_AUDIO_CLIP.CAR_MOVE)
                // 后补车位进站
                const carNode = this.getReadyCar()
                if (carNode) {
                    const carComp = carNode.getComponent(Car)
                    carComp.setMove(GAME_DATA.CAR_POSX[2], GAME_DATA.CAR_POSX[3])
                }
                break
        }
    }

    onCarMoveEndCallBack(carComp: Car) {
        if (carComp.xEnd == GAME_DATA.CAR_POSX[3]) {
            // 检查候车人员
            let inCar = false
            DataManager.instance.mapTargetMark.forEach((playComp: Player) => {
                if (playComp.colorIndex == carComp.colorIndex && playComp.state == PLAYER_STATE.WAIT) {
                    inCar = true
                    playComp.setMoveCar(true)
                }
            })
            if (inCar) AudioManager.instance.playSound(ENUM_AUDIO_CLIP.CAR_OPEN)
        } else if (carComp.xEnd == GAME_DATA.CAR_POSX[4]) {
            // 移除出站车辆
            carComp.node.removeFromParent()
            // 判定游戏胜利
            if (this.carColorIndexArr.length <= 0 && this.carRoot.children.length <= 0) {
                if (DataManager.instance.mode == ENUM_GAME_MODE.NORMAL) {
                    StaticInstance.gameManager.onGameOver(ENUM_UI_TYPE.WIN)
                } else {
                    StaticInstance.gameManager.onGameOverPk(true)
                }
            }
        }
    }

    hasPlayer(state: PLAYER_STATE) {
        return this.playerRoot.children.find(player => player.getComponent(Player).state == state)
    }

    // 获取锁住格子
    getLockBoard() {
        let board = null
        board = this.board.children.find(board => board.getChildByName('locked'))
        return board
    }

    // 补位
    onPlayerCover(pos: { x: number, y: number }[]) {
        // 排序
        sort(pos, 'y', false)
        for (let i = 0; i < pos.length; i++) {
            const { x, y } = pos[i]
            // 补位
            if (this.playerColorIndexArr.length) {
                const colorIndex = this.playerColorIndexArr.pop()
                const playerAppend = PoolManager.instance.getNode('Player', this.playerRoot)
                const playerAppendComp = playerAppend.getComponent(Player)
                playerAppendComp.setColor(colorIndex)
                const board = DataManager.instance.mapBoards.get(x + 7 * GAME_DATA.BOARD_SIZE)
                playerAppend.setPosition(board.x, board.y - GAME_DATA.BOARD_SIZE)
                playerAppend.opacity = 0
                playerAppendComp.setPosByMove(x, 7, () => {
                    playerAppendComp.appendInit()
                })
            }
            // 移动
            const players = this.playerRoot.children
            for (let j = y + 1; j <= 7; j++) {
                const player = players.find(player => player.getComponent(Player).posX == x && player.getComponent(Player).posY == j)
                if (player) {
                    const playerComp = player.getComponent(Player)
                    playerComp.setPosByMove(x, j - 1)
                }
            }
        }
        this.scheduleOnce(() => {
            DataManager.instance.isCovering = false
        }, 0.3)
    }
}
